package com.sinosoft.sinopay.web.util;

import java.math.BigDecimal;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import net.sf.json.JSONObject;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import com.sinosoft.sinocloud.platform.common.util.SecurityUtil;

/**
 * Created by zhouxin on 20160920.
 */
public class SignatureUtil {
    static Logger logger = Logger.getLogger(SignatureUtil.class);
    private static String token = "gllic";
    /** 分隔符 */
	private static final String signal ="|";
	
    public static boolean checkSignature(String signature, String timestamp, String nonce, String tk) {
        if(StringUtils.isEmpty(tk)){
            tk = token;
        }
        String[] arr = {tk, timestamp, nonce};
        if(arr != null && arr.length > 0){
            // 将token、timestamp、nonce三个参数进行字典序排序
            Arrays.sort(arr);
            StringBuilder content = new StringBuilder();
            for (int i = 0; i < arr.length; i++) {
                content.append(arr[i]);
            }

            String str = "";
            try {
                MessageDigest md = MessageDigest.getInstance("SHA-1");
                byte[] bt = md.digest(content.toString().getBytes());
                str = byteToStr(bt);
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
            logger.error("signature="+str+",weix-signature="+signature);
            return str != null ? str.equals(signature.toUpperCase()) : false;
        }
        return false;
    }

    /**
     * 将字节数组转换为十六进制字符串
     *
     * @param byteArray
     * @return
     */
    private static String byteToStr(byte[] byteArray) {
        String strDigest = "";
        for (int i = 0; i < byteArray.length; i++) {
            strDigest += byteToHexStr(byteArray[i]);
        }
        return strDigest;
    }

    /**
     * 将字节转换为十六进制字符串
     *
     * @param mByte
     * @return
     */
    private static String byteToHexStr(byte mByte) {
        char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
        char[] tempArr = new char[2];
        tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
        tempArr[1] = Digit[mByte & 0X0F];

        String s = new String(tempArr);
        return s;
    }
    
    /**
     * 生成签名方法
     */
    public static String generateSign(Object xml,String apiKey) {
    	StringBuffer paramStr = new StringBuffer();
    	JSONObject json = JSONObject.fromObject(xml);
    	List<String> keyList = new ArrayList<String>();
    	for(Object key : json.keySet()) {
    		if("sign".equals(key)) {
    			continue;
    		}
    		keyList.add(key.toString());
    	}
    	Collections.sort(keyList);
    	for (String key : keyList) {
    		if(json.getString(key).trim().isEmpty()) {
    			continue;
    		}
    		paramStr.append(key).append("=").append(json.getString(key).trim()).append("&");
		}
    	paramStr.append("key=").append(apiKey);
    	System.out.println(paramStr.toString());
    	return MD5.MD5Encode(paramStr.toString()).toUpperCase();
    }
    
    public static String generateSign(Object obj) {
    	StringBuffer paramStr = new StringBuffer();
    	JSONObject json = JSONObject.fromObject(obj);
    	List<String> keyList = new ArrayList<String>();
    	for(Object key : json.keySet()) {
    		if("sign".equals(key)) {
    			continue;
    		}
    		keyList.add(key.toString());
    		keyList.add(key.toString());
    	}
    	Collections.sort(keyList);
    	for (int i = 0; i < keyList.size(); i++) {
    		if(json.getString(keyList.get(i)).trim().isEmpty()) {
    			continue;
    		}
    		paramStr.append(keyList.get(i)).append("=").append(json.getString(keyList.get(i)).trim().toUpperCase());
    		if(i < keyList.size() - 1) {
    			paramStr.append("&");
    		}
		}
    	return MD5.MD5Encode(paramStr.toString()).toUpperCase();
    }
    /**
     * @Title: PaySignature 
     * @Description: 支付签名
     * @param @param params 
     * @param @param apiKey 私钥
     * @param @return  
     * @return String
     * @throws
     */
    public static String PaySignature(Map<String, String> params,String apiKey) {
		   Map<String, String> sortMap = new TreeMap<String, String>();
		   sortMap.putAll(params);
		   // 以"v1"+"v2"+"v3"...方式拼接参数
		   StringBuilder builder = new StringBuilder();
		   for (Map.Entry<String, String> s : sortMap.entrySet()) {
		       String v = s.getValue();
		       if (StringUtils.isBlank(v)) {// 过滤空值
		           continue;
		       }
		       builder.append(v);
		   }
		   System.out.println("--------------"+builder);
		   String sign="";
			try {
				sign = DigestUtils.signMD5(builder.toString(), apiKey);
			} catch (Exception e) {
				e.printStackTrace();
			}
		   return sign;
		}
    
    
    public static String encryMD5(Map<String,String> encryMsgs,String signKey) throws Exception{
    	//校验信息完整性
        if(signKey==null || "".equals(signKey.trim()) || encryMsgs==null || encryMsgs.size()<1){
        	logger.info("签名信息不完整！");
        }
    
        //首先对非空数据进行排序
        TreeMap<String,String> treeMap = new TreeMap<String, String>();
        for (String tKey : encryMsgs.keySet()) {
            String tValue = encryMsgs.get(tKey);
            if(tValue!=null && !"".equals(tValue)){
                treeMap.put(tKey, encryMsgs.get(tKey));
            }
        }
        treeMap.put("key",signKey);
        //拼接字符串
        StringBuffer sb = new StringBuffer();
        for (String tKey : treeMap.keySet()) {
        	String value = treeMap.get(tKey);
        	if("payAmount".equals(tKey)){
        		value = transAmount(new BigDecimal(value));
        	}
            sb.append(tKey);
            sb.append("=");
            sb.append(value);
            sb.append(signal);
        }
        String tToEncryStr = sb.toString().substring(0, sb.length()-1);
        logger.info("拼接后的签名参数："+tToEncryStr);
        //签名
        String md5Check = SecurityUtil.Md5(tToEncryStr+signKey);
        return md5Check;
    }
    private static String transAmount(BigDecimal tPayAmount) {
        BigDecimal fen = tPayAmount.multiply(new BigDecimal("100"));
        long fenAmount = fen.intValue();
        String money = String.valueOf(fenAmount);
        return money;
	}
    
    
}
